package com.uniflow.service;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.uniflow.entity.DataSync;
import com.uniflow.entity.DataSyncLog;
import com.uniflow.mapper.DataSyncLogMapper;
import com.uniflow.mapper.DataSyncMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 数据同步日志服务类
 */
@Service
public class DataSyncLogService extends ServiceImpl<DataSyncLogMapper, DataSyncLog> {
    
    @Autowired
    private DataSyncLogMapper dataSyncLogMapper;
    
    @Autowired
    private DataSyncMapper dataSyncMapper;
    
    @Autowired
    private ObjectMapper objectMapper;
    
    /**
     * 分页查询数据同步日志
     */
    public IPage<DataSyncLog> getPageList(Integer pageNum, Integer pageSize, String syncId, String status,
                                          String triggerType, LocalDateTime startTime, LocalDateTime endTime,
                                          String keyword, String tenantId) {
        Page<DataSyncLog> page = new Page<>(pageNum, pageSize);
        IPage<DataSyncLog> result = dataSyncLogMapper.selectPageList(page, syncId, status, triggerType,
                startTime, endTime, keyword, tenantId);
        
        // 丰富数据同步日志信息
        result.getRecords().forEach(this::enrichDataSyncLog);
        
        return result;
    }
    
    /**
     * 根据ID查询数据同步日志
     */
    public DataSyncLog getById(String id, String tenantId) {
        DataSyncLog log = dataSyncLogMapper.selectById(id);
        if (log != null && tenantId.equals(log.getTenantId())) {
            enrichDataSyncLog(log);
            return log;
        }
        return null;
    }
    
    /**
     * 根据同步任务ID查询日志
     */
    public List<DataSyncLog> getBySyncId(String syncId, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectBySyncId(syncId, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 根据批次号查询日志
     */
    public List<DataSyncLog> getByBatchNo(String batchNo, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectByBatchNo(batchNo, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 根据状态查询日志
     */
    public List<DataSyncLog> getByStatus(String status, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectByStatus(status, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 根据触发方式查询日志
     */
    public List<DataSyncLog> getByTriggerType(String triggerType, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectByTriggerType(triggerType, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 根据触发人查询日志
     */
    public List<DataSyncLog> getByTriggeredBy(String triggeredBy, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectByTriggeredBy(triggeredBy, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 查询正在运行的日志
     */
    public List<DataSyncLog> getRunningLogs(String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectRunningLogs(tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 查询失败的日志
     */
    public List<DataSyncLog> getFailedLogs(String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectFailedLogs(tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 查询最近的日志
     */
    public List<DataSyncLog> getRecentLogs(Integer limit, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectRecentLogs(limit, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 查询指定同步任务的最新日志
     */
    public DataSyncLog getLatestBySyncId(String syncId, String tenantId) {
        DataSyncLog log = dataSyncLogMapper.selectLatestBySyncId(syncId, tenantId);
        if (log != null) {
            enrichDataSyncLog(log);
        }
        return log;
    }
    
    /**
     * 查询指定同步任务的最后成功日志
     */
    public DataSyncLog getLastSuccessBySyncId(String syncId, String tenantId) {
        DataSyncLog log = dataSyncLogMapper.selectLastSuccessBySyncId(syncId, tenantId);
        if (log != null) {
            enrichDataSyncLog(log);
        }
        return log;
    }
    
    /**
     * 查询指定同步任务的最后失败日志
     */
    public DataSyncLog getLastFailureBySyncId(String syncId, String tenantId) {
        DataSyncLog log = dataSyncLogMapper.selectLastFailureBySyncId(syncId, tenantId);
        if (log != null) {
            enrichDataSyncLog(log);
        }
        return log;
    }
    
    /**
     * 查询长时间运行的日志
     */
    public List<DataSyncLog> getLongRunningLogs(Integer minutes, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectLongRunningLogs(minutes, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 查询执行时间超过阈值的日志
     */
    public List<DataSyncLog> getSlowLogs(Long durationThreshold, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectSlowLogs(durationThreshold, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 创建数据同步日志
     */
    @Transactional
    public DataSyncLog createLog(DataSyncLog log) {
        // 设置基础信息
        log.setId(UUID.randomUUID().toString());
        log.setCreatedTime(LocalDateTime.now());
        
        // 设置默认值
        if (log.getStatus() == null) {
            log.setStatus("running");
        }
        if (log.getStartTime() == null) {
            log.setStartTime(LocalDateTime.now());
        }
        if (log.getProgress() == null) {
            log.setProgress(0);
        }
        if (log.getTotalSteps() == null) {
            log.setTotalSteps(1);
        }
        if (log.getStepProgress() == null) {
            log.setStepProgress(0);
        }
        
        // 序列化JSON字段
        serializeJsonFields(log);
        
        dataSyncLogMapper.insert(log);
        return getById(log.getId(), log.getTenantId());
    }
    
    /**
     * 更新数据同步日志
     */
    @Transactional
    public DataSyncLog updateLog(DataSyncLog log) {
        DataSyncLog existing = dataSyncLogMapper.selectById(log.getId());
        if (existing == null) {
            throw new RuntimeException("数据同步日志不存在");
        }
        
        // 序列化JSON字段
        serializeJsonFields(log);
        
        dataSyncLogMapper.updateById(log);
        return getById(log.getId(), log.getTenantId());
    }
    
    /**
     * 开始执行
     */
    @Transactional
    public DataSyncLog startExecution(String syncId, String syncName, String triggerType,
                                      String triggeredBy, String triggeredByName, String tenantId) {
        DataSyncLog log = new DataSyncLog();
        log.setSyncId(syncId);
        log.setSyncName(syncName);
        log.setBatchNo(generateBatchNo());
        log.setTriggerType(triggerType);
        log.setTriggeredBy(triggeredBy);
        log.setTriggeredByName(triggeredByName);
        log.setTenantId(tenantId);
        
        // 设置服务器信息
        try {
            log.setServerIp(java.net.InetAddress.getLocalHost().getHostAddress());
            log.setServerHostname(java.net.InetAddress.getLocalHost().getHostName());
        } catch (Exception e) {
            // 忽略错误
        }
        log.setProcessId(java.lang.management.ManagementFactory.getRuntimeMXBean().getName().split("@")[0]);
        log.setThreadId(String.valueOf(Thread.currentThread().getId()));
        
        return createLog(log);
    }
    
    /**
     * 完成执行
     */
    @Transactional
    public boolean completeExecution(String id, String status, String result, String errorMessage) {
        DataSyncLog log = dataSyncLogMapper.selectById(id);
        if (log == null) {
            return false;
        }
        
        log.setStatus(status);
        log.setResult(result);
        log.setErrorMessage(errorMessage);
        log.setEndTime(LocalDateTime.now());
        log.setProgress(100);
        
        // 计算执行时长
        log.calculateDuration();
        
        return dataSyncLogMapper.updateById(log) > 0;
    }
    
    /**
     * 更新执行进度
     */
    @Transactional
    public boolean updateProgress(String id, Integer progress, String currentStep, Integer stepProgress) {
        return dataSyncLogMapper.updateProgress(id, progress, currentStep, stepProgress) > 0;
    }
    
    /**
     * 更新执行统计
     */
    @Transactional
    public boolean updateExecutionStats(String id, Long processedRecords, Long successRecords,
                                        Long failureRecords, Long skippedRecords, Long insertRecords,
                                        Long updateRecords, Long deleteRecords) {
        return dataSyncLogMapper.updateExecutionStats(id, processedRecords, successRecords,
                failureRecords, skippedRecords, insertRecords, updateRecords, deleteRecords) > 0;
    }
    
    /**
     * 更新错误信息
     */
    @Transactional
    public boolean updateError(String id, String errorMessage, String errorStack) {
        return dataSyncLogMapper.updateError(id, errorMessage, errorStack) > 0;
    }
    
    /**
     * 批量删除日志
     */
    @Transactional
    public boolean batchDeleteLogs(List<String> ids) {
        return dataSyncLogMapper.batchDelete(ids) > 0;
    }
    
    /**
     * 根据同步任务ID删除日志
     */
    @Transactional
    public boolean deleteBySyncId(String syncId) {
        return dataSyncLogMapper.deleteBySyncId(syncId) > 0;
    }
    
    /**
     * 删除过期日志
     */
    @Transactional
    public boolean deleteExpiredLogs(LocalDateTime expireTime, String tenantId) {
        return dataSyncLogMapper.deleteExpiredLogs(expireTime, tenantId) > 0;
    }
    
    /**
     * 清理指定状态的日志
     */
    @Transactional
    public boolean cleanupByStatus(String status, LocalDateTime beforeTime, String tenantId) {
        return dataSyncLogMapper.cleanupByStatus(status, beforeTime, tenantId) > 0;
    }
    
    /**
     * 获取日志统计信息
     */
    public Map<String, Object> getStatistics(String tenantId) {
        return dataSyncLogMapper.getStatistics(tenantId);
    }
    
    /**
     * 按状态统计日志数量
     */
    public List<Map<String, Object>> getStatsByStatus(String tenantId) {
        return dataSyncLogMapper.getStatsByStatus(tenantId);
    }
    
    /**
     * 按触发方式统计日志数量
     */
    public List<Map<String, Object>> getStatsByTriggerType(String tenantId) {
        return dataSyncLogMapper.getStatsByTriggerType(tenantId);
    }
    
    /**
     * 按同步任务统计日志数量
     */
    public List<Map<String, Object>> getStatsBySyncId(String tenantId) {
        return dataSyncLogMapper.getStatsBySyncId(tenantId);
    }
    
    /**
     * 按触发人统计日志数量
     */
    public List<Map<String, Object>> getStatsByTriggeredBy(String tenantId) {
        return dataSyncLogMapper.getStatsByTriggeredBy(tenantId);
    }
    
    /**
     * 按时间统计日志数量
     */
    public List<Map<String, Object>> getStatsByTime(LocalDateTime startTime, LocalDateTime endTime,
                                                     String timeUnit, String tenantId) {
        return dataSyncLogMapper.getStatsByTime(startTime, endTime, timeUnit, tenantId);
    }
    
    /**
     * 按月份统计日志数量
     */
    public List<Map<String, Object>> getStatsByMonth(Integer year, String tenantId) {
        return dataSyncLogMapper.getStatsByMonth(year, tenantId);
    }
    
    /**
     * 获取执行成功率统计
     */
    public Map<String, Object> getSuccessRateStats(String tenantId) {
        return dataSyncLogMapper.getSuccessRateStats(tenantId);
    }
    
    /**
     * 获取平均执行时间统计
     */
    public Map<String, Object> getAvgExecutionTimeStats(String tenantId) {
        return dataSyncLogMapper.getAvgExecutionTimeStats(tenantId);
    }
    
    /**
     * 获取执行性能统计
     */
    public Map<String, Object> getPerformanceStats(String tenantId) {
        return dataSyncLogMapper.getPerformanceStats(tenantId);
    }
    
    /**
     * 获取错误统计
     */
    public Map<String, Object> getErrorStats(String tenantId) {
        return dataSyncLogMapper.getErrorStats(tenantId);
    }
    
    /**
     * 获取今日执行统计
     */
    public Map<String, Object> getTodayStats(String tenantId) {
        return dataSyncLogMapper.getTodayStats(tenantId);
    }
    
    /**
     * 获取本周执行统计
     */
    public Map<String, Object> getWeeklyStats(String tenantId) {
        return dataSyncLogMapper.getWeeklyStats(tenantId);
    }
    
    /**
     * 获取本月执行统计
     */
    public Map<String, Object> getMonthlyStats(String tenantId) {
        return dataSyncLogMapper.getMonthlyStats(tenantId);
    }
    
    /**
     * 获取同步任务执行趋势
     */
    public List<Map<String, Object>> getExecutionTrend(String syncId, Integer days, String tenantId) {
        return dataSyncLogMapper.getExecutionTrend(syncId, days, tenantId);
    }
    
    /**
     * 获取同步任务性能趋势
     */
    public List<Map<String, Object>> getPerformanceTrend(String syncId, Integer days, String tenantId) {
        return dataSyncLogMapper.getPerformanceTrend(syncId, days, tenantId);
    }
    
    /**
     * 获取同步任务错误趋势
     */
    public List<Map<String, Object>> getErrorTrend(String syncId, Integer days, String tenantId) {
        return dataSyncLogMapper.getErrorTrend(syncId, days, tenantId);
    }
    
    /**
     * 查询执行历史
     */
    public List<DataSyncLog> getExecutionHistory(String syncId, Integer limit, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectExecutionHistory(syncId, limit, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 查询执行详情
     */
    public DataSyncLog getExecutionDetail(String id, String tenantId) {
        DataSyncLog log = dataSyncLogMapper.selectExecutionDetail(id, tenantId);
        if (log != null) {
            enrichDataSyncLog(log);
        }
        return log;
    }
    
    /**
     * 查询相关执行
     */
    public List<DataSyncLog> getRelatedExecutions(String batchNo, String tenantId) {
        List<DataSyncLog> list = dataSyncLogMapper.selectRelatedExecutions(batchNo, tenantId);
        list.forEach(this::enrichDataSyncLog);
        return list;
    }
    
    /**
     * 生成批次号
     */
    private String generateBatchNo() {
        return "BATCH_" + System.currentTimeMillis() + "_" + UUID.randomUUID().toString().substring(0, 8).toUpperCase();
    }
    
    /**
     * 序列化JSON字段
     */
    private void serializeJsonFields(DataSyncLog log) {
        try {
            if (log.getParameters() != null) {
                log.setParametersJson(objectMapper.writeValueAsString(log.getParameters()));
            }
            if (log.getConfig() != null) {
                log.setConfigJson(objectMapper.writeValueAsString(log.getConfig()));
            }
            if (log.getDetails() != null) {
                log.setDetailsJson(objectMapper.writeValueAsString(log.getDetails()));
            }
            if (log.getMetrics() != null) {
                log.setMetricsJson(objectMapper.writeValueAsString(log.getMetrics()));
            }
        } catch (Exception e) {
            throw new RuntimeException("JSON序列化失败", e);
        }
    }
    
    /**
     * 反序列化JSON字段
     */
    private void deserializeJsonFields(DataSyncLog log) {
        try {
            if (StringUtils.hasText(log.getParametersJson())) {
                log.setParameters(objectMapper.readValue(log.getParametersJson(), new TypeReference<Map<String, Object>>() {}));
            }
            if (StringUtils.hasText(log.getConfigJson())) {
                log.setConfig(objectMapper.readValue(log.getConfigJson(), new TypeReference<Map<String, Object>>() {}));
            }
            if (StringUtils.hasText(log.getDetailsJson())) {
                log.setDetails(objectMapper.readValue(log.getDetailsJson(), new TypeReference<Map<String, Object>>() {}));
            }
            if (StringUtils.hasText(log.getMetricsJson())) {
                log.setMetrics(objectMapper.readValue(log.getMetricsJson(), new TypeReference<Map<String, Object>>() {}));
            }
        } catch (Exception e) {
            // 忽略反序列化错误
        }
    }
    
    /**
     * 丰富数据同步日志信息
     */
    private void enrichDataSyncLog(DataSyncLog log) {
        if (log == null) {
            return;
        }
        
        // 反序列化JSON字段
        deserializeJsonFields(log);
        
        // 设置计算字段
        log.setSuccessRate(log.getSuccessRate());
        log.setFailureRate(log.getFailureRate());
        log.setProcessSpeed(log.getProcessSpeed());
        log.setRunning(log.isRunning());
        log.setDurationDesc(log.formatDuration());
        
        // 加载同步任务信息
        if (StringUtils.hasText(log.getSyncId())) {
            DataSync syncInfo = dataSyncMapper.selectById(log.getSyncId());
            log.setSyncInfo(syncInfo);
        }
    }
}